#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cre2.h>

#define PRINTF(...) { printf(__VA_ARGS__);         fflush(stdout); }
#define FWRITE(...) { fwrite(__VA_ARGS__, stdout); fflush(stdout); }

int main (void)
{
    { /* 利用完整匹配替换第一个匹配 */
        cre2_regexp_t *rex;
        const char *pattern = "ciao hello salut";
        const char *text = "OK ciao hello salut OK";
        const char * replace = "pre \\0 post";
        cre2_string_t target = {.data = text, .length = strlen(text)};
        cre2_string_t rewrite = {.data = replace, .length = strlen(replace)};
        int result;

        rex = cre2_new(pattern, strlen(pattern), NULL);

        {
            result = cre2_replace_re(rex, &target, &rewrite);
            PRINTF("repalce full match ret = %d\n", result);

            if (1 != result)
                goto error;
            if ('\0' != target.data[target.length])
                goto error;

            PRINTF("rewritten to: ");
            FWRITE(target.data, target.length, 1);
            PRINTF("\n");
        }

        cre2_delete(rex);
        free((void *)target.data);
    }
    { /* 用指定字符串替换第一个匹配 */
        cre2_regexp_t *rex;
        const char *pattern = "hello";
        const char *text = "ciao hello salut hello";
        const char * replace = "ohayo";
        cre2_string_t target = {.data = text, .length = strlen(text)};
        cre2_string_t rewrite = {.data = replace, .length = strlen(replace)};
        int result;

        rex = cre2_new(pattern, strlen(pattern), NULL);

        {
            result = cre2_replace_re(rex, &target, &rewrite);
            PRINTF("repalce fix string ret = %d\n", result);

            if (1 != result)
                goto error;
            if ('\0' != target.data[target.length])
                goto error;

            PRINTF("rewritten to: ");
            FWRITE(target.data, target.length, 1);
            PRINTF("\n");
        }

        cre2_delete(rex);
        free((void *)target.data);
    }

    { /* 使用完整匹配实现全局替换 */
        cre2_regexp_t *rex;
        const char *pattern = "ciao hello salut";
        const char *text = "ciao hello salut and ciao hello salut";
        const char * replace = "pre \\0 post";
        cre2_string_t target = {.data = text, .length = strlen(text)};
        cre2_string_t rewrite = {.data = replace, .length = strlen(replace)};
        int result;

        rex = cre2_new(pattern, strlen(pattern), NULL);

        {
            result = cre2_global_replace_re(rex, &target, &rewrite);
            PRINTF("global repalce full match ret = %d\n", result);

            if (2 != result)
                goto error;
            if ('\0' != target.data[target.length])
                goto error;

            PRINTF("rewritten to: ");
            FWRITE(target.data, target.length, 1);
            PRINTF("\n");
        }

        cre2_delete(rex);
        free((void *)target.data);
    }
    { /* 用指定字符串实现全局替换 */
        cre2_regexp_t *rex;
        const char *pattern = "hello";
        const char *text = "ciao hello salut";
        const char * replace = "ohayo";
        cre2_string_t target = {.data = text, .length = strlen(text)};
        cre2_string_t rewrite = {.data = replace, .length = strlen(replace)};
        int result;

        rex = cre2_new(pattern, strlen(pattern), NULL);

        {
            result = cre2_global_replace_re(rex, &target, &rewrite);
            PRINTF("global repalce fix string ret = %d\n", result);

            if (1 != result)
                goto error;
            if ('\0' != target.data[target.length])
                goto error;

            PRINTF("rewritten to: ");
            FWRITE(target.data, target.length, 1);
            PRINTF("\n");
        }

        cre2_delete(rex);
        free((void *)target.data);
    }
    { /* 用参数化字符串替换多个子字符串 */
        cre2_regexp_t *rex;
        const char *pattern = "[a-z]+\\(([0-9]+)\\)";
        const char *text = "ciao(1) hello(2) salut(3)";
        const char * replace = "ohayo(\\1)";
        cre2_string_t target = {.data = text, .length = strlen(text)};
        cre2_string_t rewrite = {.data = replace, .length = strlen(replace)};
        int result;

        rex = cre2_new(pattern, strlen(pattern), NULL);

        {
            result = cre2_global_replace_re(rex, &target, &rewrite);
            PRINTF("multi replace ret = %d\n", result);

            if (3 != result) /* 3 substitutions */
                goto error;
            if ('\0' != target.data[target.length])
                goto error;

            PRINTF("result %d, rewritten to: ", result);
            FWRITE(target.data, target.length, 1);
            PRINTF("\n");
        }

        cre2_delete(rex);
        free((void *)target.data);
    }

    { /* 用完整匹配提取子字符串，并替换 */
        cre2_regexp_t *rex;
        const char *pattern = "ciao hello salut";
        const char *text = "OK ciao hello salut NO";
        const char * replace = "pre \\0 post";
        cre2_string_t input = {.data = text, .length = strlen(text)};
        cre2_string_t rewrite = {.data = replace, .length = strlen(replace)};
        cre2_string_t target;
        int result;

        rex = cre2_new(pattern, strlen(pattern), NULL);

        {
            result = cre2_extract_re(rex, &input, &rewrite, &target);
            PRINTF("extract full match ret = %d\n", result);

            if (1 != result)
                goto error;
            if ('\0' != target.data[target.length])
                goto error;

            PRINTF("rewritten to: ");
            FWRITE(target.data, target.length, 1);
            PRINTF("\n");
        }

        cre2_delete(rex);
        free((void *)target.data);
    }
    { /* 提取匹配子字符串，并替换为新串 */
        cre2_regexp_t *rex;
        const char *pattern = "hello([0-9]+)";
        const char *text = "ciao hello123 salut";
        const char * replace = "ohayo\\1";
        cre2_string_t input = {.data = text, .length = strlen(text)};
        cre2_string_t rewrite = {.data = replace, .length = strlen(replace)};
        cre2_string_t target;
        int result;

        rex = cre2_new(pattern, strlen(pattern), NULL);

        {
            result = cre2_extract_re(rex, &input, &rewrite, &target);
            PRINTF("extract fix string ret = %d\n", result);

            if (1 != result)
                goto error;
            if ('\0' != target.data[target.length])
                goto error;

            PRINTF("rewritten to: ");
            FWRITE(target.data, target.length, 1);
            PRINTF("\n");
        }

        cre2_delete(rex);
        free((void *)target.data);
    }

    exit(EXIT_SUCCESS);
error:
    exit(EXIT_FAILURE);
}
